﻿using System;

namespace EnterpriseLibraryExtensions.Services.Mapping
{
    /// <summary>
    /// The <see cref="EnterpriseLibraryExtensions.Services.Mapping.IEntityTranslatorService"/> interface exposes all the functionality
    /// needed to register entity mapper translators and actually using them for translation.
    /// </summary>
    public interface IEntityTranslatorService
    {
        /// <summary>
        /// Returns whether or not the service is capable of translating betweeen the two provided types with the 
        /// currently registered translators.
        /// </summary>
        /// <param name="targetType">The type to translate to.</param>
        /// <param name="sourceType">The type to translate from.</param>
        /// <returns>True if translation is possible. Otherwise false.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown if either <paramref name="targetType"/> or <paramref name="sourceType"/> are null.</exception>
        bool CanTranslate(Type targetType, Type sourceType);

        /// <summary>
        /// Returns whether or not the service is capable of translating betweeen the two provided types with the 
        /// currently registered translators.
        /// </summary>
        /// <typeparam name="TTarget">The type to translate to.</typeparam>
        /// <typeparam name="TSource">The type to translate from.</typeparam>
        /// <returns>True if translation is possible. Otherwise false.</returns>
        bool CanTranslate<TTarget, TSource>();

        /// <summary>
        /// Translate the <paramref name="source"/> instance into the type specified by the <paramref name="targetType"/> parameter.
        /// </summary>
        /// <param name="targetType">The desired target type.</param>
        /// <param name="source">The source instance.</param>
        /// <returns>The translated instance.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown if <paramref name="source"/> or <paramref name="targetType"/> are null.</exception>
        /// <exception cref="System.InvalidOperationException">Thrown if no translators can handle the translation.</exception>
        object Translate(Type targetType, object source);

        /// <summary>
        /// Translate the source instance into the type specified by the generic argument TTarget.
        /// </summary>
        /// <typeparam name="TTarget">The desired target type.</typeparam>
        /// <param name="source">The source instance.</param>
        /// <returns>The translated instance.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown if <paramref name="source"/> is null.</exception>
        /// <exception cref="System.InvalidOperationException">Thrown if no translators can handle the translation.</exception>
        TTarget Translate<TTarget>(object source);

        /// <summary>
        /// Register a new <paramref name="entityTranslator"/> in the service.
        /// </summary>
        /// <param name="entityTranslator">A valid entityTranslator.</param>
        /// <exception cref="System.ArgumentNullException">Thrown if <paramref name="entityTranslator"/> is null.</exception>"
        void RegisterEntityTranslator(IEntityTranslator entityTranslator);

        /// <summary>
        /// Removes a translator already registered in the service.
        /// </summary>
        /// <param name="entityTranslator">A valid, already registered translator.</param>
        /// <exception cref="System.ArgumentNullException">Thrown if <paramref name="entityTranslator"/> is null.</exception>
        void RemoveEntityTranslator(IEntityTranslator entityTranslator);
    }

}
